//-------------------------------------------------------------------------
// File: Variant.cpp
//
// Descr.: - todo -
//
// Author: Stefan Leihkauf
// Date:   11.08.2013
//-------------------------------------------------------------------------
#include "cb_pch.h"
#include "Variant.h"

struct VariantTypeName{
    Variant::Type Type;
    std::string Name;
};

boost::array<VariantTypeName, 14> VariantTypeNameList = {
    {
        {Variant::Invalid,		"invalid"   },
        {Variant::Bool,			"bool"      },
        {Variant::Char,			"char"      },
        {Variant::UChar,		"uchar"     },
        {Variant::Short,		"short"     },     
        {Variant::UShort,		"ushort"    },
        {Variant::Int,			"int"       },
        {Variant::UInt,			"uint"      },
        {Variant::Long,			"long"      },
        {Variant::ULong,		"ulong"     },
		{Variant::LongLong,		"longlong"  },
		{Variant::ULongLong,    "ulonglong" },
		{Variant::Float,		"float"		},
		{Variant::Double,		"double"	}
    }
};

//-----------------------------------------------------------------------------
Variant::Variant() :
    _type(Variant::Invalid)
{
}

//-----------------------------------------------------------------------------
Variant::Variant(const Variant& variant) :
    _type(variant._type),
    _data(variant._data)
{
}

//-----------------------------------------------------------------------------
Variant::Variant(Variant::Type type) :
    _type(type)
{
    memset(&_data, 0, sizeof(Data));
}

//-----------------------------------------------------------------------------
Variant::Variant(bool val) :
    _type(Variant::Bool)
{
    _data._bool = val;
}

//-----------------------------------------------------------------------------
Variant::Variant(char val) :
    _type(Variant::Char)
{
    _data._char = val;
}

//-----------------------------------------------------------------------------
Variant::Variant(unsigned char val) :
    _type(Variant::UChar)
{
    _data._uchar = val;
}

//-----------------------------------------------------------------------------
Variant::Variant(short val) :
    _type(Variant::Short)
{
    _data._short = val;
}

//-----------------------------------------------------------------------------
Variant::Variant(unsigned short val) :
    _type(Variant::UShort)
{
    _data._ushort = val;
}
//-----------------------------------------------------------------------------
Variant::Variant(int val) :
    _type(Variant::Int)
{
    _data._int = val;
}

//-----------------------------------------------------------------------------
Variant::Variant(unsigned int val) :
    _type(Variant::UInt)
{
    _data._uint = val;
}

//-----------------------------------------------------------------------------
Variant::Variant(long val) :
    _type(Variant::Long)
{
    _data._long = val;
}

//-----------------------------------------------------------------------------
Variant::Variant(unsigned long val) :
    _type(Variant::ULong)
{
    _data._ulong = val;
}

//-----------------------------------------------------------------------------
Variant::Variant(long long val) :
	_type(Variant::LongLong)
{
	_data._longlong = val;
}

//-----------------------------------------------------------------------------
Variant::Variant(unsigned long long val) :
	_type(Variant::ULongLong)
{
	_data._ulonglong = val;
}

//-----------------------------------------------------------------------------
Variant::Variant(float val) :
	_type(Variant::Float)
{
	_data._float = val;
}

//-----------------------------------------------------------------------------
Variant::Variant(double val) :
	_type(Variant::Double)
{
	_data._double = val;
}

//-----------------------------------------------------------------------------
Variant::~Variant()
{
}

//-----------------------------------------------------------------------------
Variant::Type Variant::getType() const
{
    return _type;
}

//-----------------------------------------------------------------------------
std::string Variant::getTypeName() const
{
    for(unsigned i = 0; i < VariantTypeNameList.size(); i++) {
        if(VariantTypeNameList[i].Type == _type)
            return VariantTypeNameList[i].Name;
    }
    
    return std::string();
}

//-----------------------------------------------------------------------------
Variant& Variant::operator = (const Variant& other)
{
    if(this == &other)
        return *this; // self assignment
    
    _type = other._type;
    _data = other._data;
    
    /* If we once support user defined varaiant data types then we need
     * to decide how to copy them.
     */
    
    return *this;
}

//-----------------------------------------------------------------------------
bool Variant::operator == (const Variant& other) const
{
    if(this == &other)
        return true; // self quality
    
    if((this->_type == other._type)) {
        switch(_type) {
		case Variant::Bool:			return (_data._bool == other._data._bool);			break;
		case Variant::Char:			return (_data._char == other._data._char);			break;
		case Variant::UChar:		return (_data._uchar == other._data._uchar);		break;
		case Variant::Short:		return (_data._short == other._data._short);		break;
		case Variant::UShort:		return (_data._ushort == other._data._ushort);		break;
		case Variant::Int:			return (_data._int == other._data._int);			break;
		case Variant::UInt:			return (_data._uint == other._data._uint);			break;
		case Variant::Long:			return (_data._long == other._data._long);			break;
		case Variant::ULong:		return (_data._ulong == other._data._ulong);		break;
		case Variant::LongLong:		return (_data._longlong == other._data._longlong);  break;
		case Variant::ULongLong:    return (_data._ulonglong == other._data._ulonglong);break;
		case Variant::Float:		return (_data._float == other._data._float);		break;
		case Variant::Double:		return (_data._double == other._data._double);		break;
        
        // todo: add user defined variant comparisions here
        
        default: return false;
        }        
    }
    
    return false;
}

//-----------------------------------------------------------------------------
bool Variant::operator != (const Variant& other) const
{
    return !(*this == other);
}